package com.example.fengyungo_user.utils;

import android.app.Service;
import android.graphics.Bitmap;
import android.util.Log;

import androidx.fragment.app.FragmentActivity;

import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.callback.OSSProgressCallback;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSFederationCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSFederationToken;
import com.alibaba.sdk.android.oss.internal.OSSAsyncTask;
import com.alibaba.sdk.android.oss.model.GetObjectRequest;
import com.alibaba.sdk.android.oss.model.GetObjectResult;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;
import com.example.fengyungo_user.constant.OssConstant;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

public class OssUtils {

    private static final String TAG = "OssUtils";

    private static OSSFederationToken ossFederationToken = null;

    private static byte[] imageByteArray;

    private static boolean[] successUpload;

    private static boolean[] successGet;

    /**
     * 获取OSSCredentialProvider
     *
     * @return
     */
    public static OSSCredentialProvider getOSSCredentialProvider() {
        OSSCredentialProvider credentialProvider = new OSSFederationCredentialProvider() {
            @Override
            public OSSFederationToken getFederationToken() {
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        String url = OssConstant.NGROK_URL_OSS + "/distribute-token.json";
                        try {
                            Log.d(TAG, "run: okhttp");
                            String responseJson = OkHttpUtils.get(url);
                            Log.d(TAG, "run: responseJson=" + responseJson);
                            JSONObject jsonObjs = new JSONObject(responseJson);
                            String ak = jsonObjs.getString("AccessKeyId");
                            String sk = jsonObjs.getString("AccessKeySecret");
                            String token = jsonObjs.getString("SecurityToken");
                            String expiration = jsonObjs.getString("Expiration");
                            Log.d(TAG, "getFederationToken: expiration=" + expiration);
                            ossFederationToken = new OSSFederationToken(ak, sk, token, expiration);
                            successUpload = new boolean[]{true};
                        } catch (IOException | JSONException e) {
                            e.printStackTrace();
                            Log.d(TAG, "run: error:" + e.getMessage());
                            successUpload = new boolean[]{false};
                        }
                    }
                };
                ThreadPoolUtil.execute(runnable);
                while (successUpload == null) {
                }
                if (!successUpload[0]) {
                    Log.d(TAG, "getFederationToken: null");
                    return null;
                }
                while (ossFederationToken == null) {
                }
                Log.d(TAG, "getFederationToken: success");
                return ossFederationToken;
            }
        };
        return credentialProvider;
    }

    /**
     * 上传文件到OSS
     *
     * @param fragmentActivity FragmentActivity
     * @param objectName       String，OSS的文件名
     * @param uploadFilePath   String
     */
    public static void upload(FragmentActivity fragmentActivity, String objectName, String uploadFilePath) {
        Log.d(TAG, "upload: objectName=" + objectName + ",uploadFilePath=" + uploadFilePath);
        // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1（杭州）为例，Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
        String endpoint = OssConstant.ENDPOINT;

        OSSCredentialProvider credentialProvider = getOSSCredentialProvider();
        // 创建OSSClient实例。
        OSSClient oss = new OSSClient(fragmentActivity.getApplicationContext(), endpoint, credentialProvider);

        // 构造上传请求。
        // objectName设置为
        PutObjectRequest put = new PutObjectRequest(OssConstant.BUCKET_NAME, objectName, uploadFilePath);

        // 异步上传时可以设置进度回调。
        put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
            @Override
            public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
                Log.d("PutObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
            }
        });

        OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
            @Override
            public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                Log.d("PutObject", "UploadSuccess");
                Log.d("ETag", result.getETag());
                Log.d("RequestId", result.getRequestId());
            }

            @Override
            public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
                // 请求异常。
                if (clientExcepion != null) {
                    // 本地异常，如网络异常等。
                    clientExcepion.printStackTrace();
                }
                if (serviceException != null) {
                    // 服务异常。
                    Log.e("ErrorCode", serviceException.getErrorCode());
                    Log.e("RequestId", serviceException.getRequestId());
                    Log.e("HostId", serviceException.getHostId());
                    Log.e("RawMessage", serviceException.getRawMessage());
                }
            }
        });
        // task.cancel(); // 可以取消任务。
        // task.waitUntilFinished(); // 等待上传完成。
    }

    /**
     * 从OSS获取图片
     *
     * @return Bitmap
     */
    public static Bitmap getBitmapFromOss(FragmentActivity fragmentActivity, String avatar) {
        Log.d(TAG, "getBitmapFromOss: avatar=" + avatar);
        // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1（杭州）为例，Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
        // String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        int index = avatar.lastIndexOf('/');
        String endpoint = OssConstant.ENDPOINT;
        String objectKey = avatar.substring(index + 1);

        OSSCredentialProvider credentialProvider = OssUtils.getOSSCredentialProvider();
        // 创建OSSClient实例。
        OSSClient oss = new OSSClient(fragmentActivity.getApplicationContext(), endpoint, credentialProvider);
        // 构造下载文件请求。
        GetObjectRequest get = new GetObjectRequest(OssConstant.BUCKET_NAME, objectKey);

        OSSAsyncTask task = oss.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() {
            @Override
            public void onSuccess(GetObjectRequest request, GetObjectResult result) {
                // 请求成功。
                Log.d("asyncGetObject", "DownloadSuccess");
                Log.d("Content-Length", "" + result.getContentLength());

                InputStream inputStream = result.getObjectContent();
                byte[] buffer = new byte[2048];
                int len;

                ByteArrayOutputStream outStream = new ByteArrayOutputStream();

                try {
                    while ((len = inputStream.read(buffer)) != -1) {
                        // 您可以在此处编写代码来处理下载的数据。
                        // 处理下载的数据
                        outStream.write(buffer, 0, len);
                        Log.d("asyncGetObjectSample", "read length: " + len);
                    }
                    outStream.flush();
                    imageByteArray = outStream.toByteArray();
                    Log.d(TAG, "onSuccess: imageByteArray:" + Arrays.toString(imageByteArray));
                    successGet = new boolean[]{true};
                    outStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            // GetObject请求成功，返回GetObjectResult。GetObjectResult包含一个输入流的实例。您需要自行处理返回的输入流。
            public void onFailure(GetObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
                successGet = new boolean[]{false};
                // 请求异常。
                if (clientExcepion != null) {
                    // 本地异常，如网络异常等。
                    clientExcepion.printStackTrace();
                }
                if (serviceException != null) {
                    // 服务异常。
                    Log.e("ErrorCode", serviceException.getErrorCode());
                    Log.e("RequestId", serviceException.getRequestId());
                    Log.e("HostId", serviceException.getHostId());
                    Log.e("RawMessage", serviceException.getRawMessage());
                }
            }
        });
        while (successGet == null) {
        }
        if (!successGet[0]) {
            Log.d(TAG, "getBitmapFromOss: null");
            return null;
        }
        while (imageByteArray == null) {
        }
        Bitmap bitmap = BitmapUtils.getPicFromBytes(imageByteArray, null);
        Log.d(TAG, "getBitmapFromOss: bitmap=" + bitmap);
        return bitmap;
    }

    /**
     * 从OSS获取图片
     *
     * @return Bitmap
     */
    public static Bitmap getBitmapFromOss(Service service, String avatar) {
        Log.d(TAG, "getBitmapFromOss: avatar=" + avatar);
        // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1（杭州）为例，Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
        // String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        int index = avatar.lastIndexOf('/');
        String endpoint = OssConstant.ENDPOINT;
        String objectKey = avatar.substring(index + 1);

        OSSCredentialProvider credentialProvider = OssUtils.getOSSCredentialProvider();
        // 创建OSSClient实例。
        OSSClient oss = new OSSClient(service.getApplicationContext(), endpoint, credentialProvider);
        // 构造下载文件请求。
        GetObjectRequest get = new GetObjectRequest(OssConstant.BUCKET_NAME, objectKey);

        OSSAsyncTask task = oss.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() {
            @Override
            public void onSuccess(GetObjectRequest request, GetObjectResult result) {
                // 请求成功。
                Log.d("asyncGetObject", "DownloadSuccess");
                Log.d("Content-Length", "" + result.getContentLength());

                InputStream inputStream = result.getObjectContent();
                byte[] buffer = new byte[2048];
                int len;

                ByteArrayOutputStream outStream = new ByteArrayOutputStream();

                try {
                    while ((len = inputStream.read(buffer)) != -1) {
                        // 您可以在此处编写代码来处理下载的数据。
                        // 处理下载的数据
                        outStream.write(buffer, 0, len);
                        Log.d("asyncGetObjectSample", "read length: " + len);
                    }
                    outStream.flush();
                    imageByteArray = outStream.toByteArray();
                    Log.d(TAG, "onSuccess: imageByteArray:" + Arrays.toString(imageByteArray));
                    outStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            // GetObject请求成功，返回GetObjectResult。GetObjectResult包含一个输入流的实例。您需要自行处理返回的输入流。
            public void onFailure(GetObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
                // 请求异常。
                if (clientExcepion != null) {
                    // 本地异常，如网络异常等。
                    clientExcepion.printStackTrace();
                }
                if (serviceException != null) {
                    // 服务异常。
                    Log.e("ErrorCode", serviceException.getErrorCode());
                    Log.e("RequestId", serviceException.getRequestId());
                    Log.e("HostId", serviceException.getHostId());
                    Log.e("RawMessage", serviceException.getRawMessage());
                }
            }
        });
        while (imageByteArray == null) {
        }
        Bitmap bitmap = BitmapUtils.getPicFromBytes(imageByteArray, null);
        Log.d(TAG, "getBitmapFromOss: bitmap=" + bitmap);
        return bitmap;
    }

    /**
     * 获取文件名称，并为其添加司机id为前缀
     *
     * @param localPath 本地路径
     * @return driverId+文件名称
     */
    public static String getFilename(FragmentActivity fragmentActivity, String localPath) {
        int index = localPath.lastIndexOf('/');
        String filename = UserUtils.getUserInfo(fragmentActivity).getUserId() + localPath.substring(index + 1);
        Log.d(TAG, "getFilename: filename=" + filename);
        return filename;
    }


    /**
     * 生成OSS图像的Url
     *
     * @param localPath 本地图片路径
     * @return String, url
     */
    public static String generateOssUrl(FragmentActivity fragmentActivity, String localPath) {
        String ossUrl = OssConstant.URL + getFilename(fragmentActivity, localPath);
        Log.d(TAG, "generateOssUrl: ossUrl=" + ossUrl);
        return ossUrl;
    }
}
